/**
 Copyright (c) 2010, C.A. Burrell
 All rights reserved.

 Redistribution and use in source and binary forms, with or without modification,
 are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
 * disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
 * following disclaimer in the
 documentation and/or other materials provided with the distribution.
 * Neither the name of "c-a-fe.ca" nor the names of its contributors may be used to endorse or promote products
 * derived from this
 software without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 INCLUDING, BUT NOT LIMITED TO,
 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 COPYRIGHT HOLDER OR CONTRIBUTORS
 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
 */
/**
 * @author C.A. Burrell (deltafront@gmail.com)
 */

package gaboli.common.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * Wrapper for some gaboli.common functions involving dates and times.
 *
 * @author C. Burrell (deltafront@gmail.com)
 */
public class DateTimeUtils
{
    /**
     * Default Date String for use. This string is in 'yyyyMMddHHmmssSSS' format:
     * - Four Digit Year
     * - Two digit Month; months before October (10) must use a leading '0' (zero).
     * - Two digit Day of Month; days before the tenth must use a leading '0' (zero).
     * - Two digit Hour of Day. This is using the 24-hour clock, and hours before 1000 must use a leading '0' (zero).
     * - Two digit Minute of Hour. Values less than ten (10) must use a leading '0' (zero).
     * - Two digit Seconds of Minute. Values less than ten (10) must use a leading '0' (zero).
     * - Three digit Milliseconds. Values less than one hundred (100) must use leading '0's (zeroes).
     */

    public final String defaultDateFormatString = "yyyyMMddHHmmssSSS";
    private final SimpleDateFormat defaultDateFormat = new SimpleDateFormat( defaultDateFormatString );


    /**
     * Sole overload of the getFormattedDate function that allows you to specify
     * the format of the date. The available choices are as follows (from http://java.sun
     * .com/javase/6/docs/api/java/text/SimpleDateFormat.html):
     * <table border=0 cellspacing=3 cellpadding=0 summary="Chart shows pattern letters, date/time component,
     * presentation, and examples.">
     * <tr bgcolor="#ccccff">
     * <th align=left>Letter
     * <th align=left>Date or Time Component
     * <th align=left>Presentation
     * <th align=left>Examples
     * <tr>
     * <td><code>G</code>
     * <td>Era designator
     * <td><a href="#text">Text</a>
     * <td><code>AD</code>
     * <p/>
     * <tr bgcolor="#eeeeff">
     * <td><code>y</code>
     * <td>Year
     * <td><a href="#year">Year</a>
     * <td><code>1996</code>; <code>96</code>
     * <tr>
     * <td><code>M</code>
     * <p/>
     * <td>Month in year
     * <td><a href="#month">Month</a>
     * <td><code>July</code>; <code>Jul</code>; <code>07</code>
     * <tr bgcolor="#eeeeff">
     * <td><code>w</code>
     * <td>Week in year
     * <td><a href="#number">Number</a>
     * <p/>
     * <td><code>27</code>
     * <tr>
     * <td><code>W</code>
     * <td>Week in month
     * <td><a href="#number">Number</a>
     * <td><code>2</code>
     * <tr bgcolor="#eeeeff">
     * <p/>
     * <td><code>D</code>
     * <td>Day in year
     * <td><a href="#number">Number</a>
     * <td><code>189</code>
     * <tr>
     * <td><code>d</code>
     * <td>Day in month
     * <td><a href="#number">Number</a>
     * <p/>
     * <td><code>10</code>
     * <tr bgcolor="#eeeeff">
     * <td><code>F</code>
     * <td>Day of week in month
     * <td><a href="#number">Number</a>
     * <td><code>2</code>
     * <tr>
     * <p/>
     * <td><code>E</code>
     * <td>Day in week
     * <td><a href="#text">Text</a>
     * <td><code>Tuesday</code>; <code>Tue</code>
     * <tr bgcolor="#eeeeff">
     * <td><code>a</code>
     * <p/>
     * <td>Am/pm marker
     * <td><a href="#text">Text</a>
     * <td><code>PM</code>
     * <tr>
     * <td><code>H</code>
     * <td>Hour in day (0-23)
     * <td><a href="#number">Number</a>
     * <td><code>0</code>
     * <p/>
     * <tr bgcolor="#eeeeff">
     * <td><code>k</code>
     * <td>Hour in day (1-24)
     * <td><a href="#number">Number</a>
     * <td><code>24</code>
     * <tr>
     * <td><code>K</code>
     * <p/>
     * <td>Hour in am/pm (0-11)
     * <td><a href="#number">Number</a>
     * <td><code>0</code>
     * <tr bgcolor="#eeeeff">
     * <td><code>h</code>
     * <td>Hour in am/pm (1-12)
     * <td><a href="#number">Number</a>
     * <td><code>12</code>
     * <p/>
     * <tr>
     * <td><code>m</code>
     * <td>Minute in hour
     * <td><a href="#number">Number</a>
     * <td><code>30</code>
     * <tr bgcolor="#eeeeff">
     * <td><code>s</code>
     * <p/>
     * <td>Second in minute
     * <td><a href="#number">Number</a>
     * <td><code>55</code>
     * <tr>
     * <td><code>S</code>
     * <td>Millisecond
     * <td><a href="#number">Number</a>
     * <td><code>978</code>
     * <p/>
     * <tr bgcolor="#eeeeff">
     * <td><code>z</code>
     * <td>Time zone
     * <td><a href="#timezone">General time zone</a>
     * <td><code>Pacific Standard Time</code>; <code>PST</code>; <code>GMT-08:00</code>
     * <tr>
     * <p/>
     * <td><code>Z</code>
     * <td>Time zone
     * <td><a href="#rfc822timezone">RFC 822 time zone</a>
     * <td><code>-0800</code>
     * </table>
     * <table border=0 cellspacing=3 cellpadding=0 summary="Examples of date and time patterns interpreted in the U.S
     * . locale">
     * <tr bgcolor="#ccccff">
     * <th align=left>Date and Time Pattern
     * <th align=left>Result
     * <tr>
     * <td><code>"yyyy.MM.dd G 'at' HH:mm:ss z"</code>
     * <p/>
     * <td><code>2001.07.04 AD at 12:08:56 PDT</code>
     * <tr bgcolor="#eeeeff">
     * <td><code>"EEE, MMM d, ''yy"</code>
     * <td><code>Wed, Jul 4, '01</code>
     * <tr>
     * <td><code>"h:mm a"</code>
     * <td><code>12:08 PM</code>
     * <p/>
     * <tr bgcolor="#eeeeff">
     * <td><code>"hh 'o''clock' a, zzzz"</code>
     * <td><code>12 o'clock PM, Pacific Daylight Time</code>
     * <tr>
     * <td><code>"K:mm a, z"</code>
     * <td><code>0:08 PM, PDT</code>
     * <tr bgcolor="#eeeeff">
     * <p/>
     * <td><code>"yyyyy.MMMMM.dd GGG hh:mm aaa"</code>
     * <td><code>02001.July.04 AD 12:08 PM</code>
     * <tr>
     * <td><code>"EEE, d MMM yyyy HH:mm:ss Z"</code>
     * <td><code>Wed, 4 Jul 2001 12:08:56 -0700</code>
     * <tr bgcolor="#eeeeff">
     * <td><code>"yyMMddHHmmssZ"</code>
     * <p/>
     * <td><code>010704120856-0700</code>
     * </table>
     *
     * @param calendar Calendar representation of the date.
     * @param format   format of the date as per example.
     * @return String of formatted date, or null.
     * @since 1.0
     */
    public static String getFormattedDate( Calendar calendar, String format )
    {
        String out = null;
        try
        {
            SimpleDateFormat sdf = new SimpleDateFormat( format );
            sdf.setCalendar( calendar );
            out = sdf.format( calendar.getTimeInMillis() );
        }
        catch( Exception e )
        {
            e.printStackTrace( System.err );
        }
        return out;
    }

    /**
     * Returns a date formatted in MMDDYYYY,HH:mm:ss format.
     *
     * @param calendar Calendar object.
     * @return formatted date.
     * @since 1.0
     */
    public static String getFormattedDate( Calendar calendar )
    {
        if( calendar == null )
        {
            return "";
        }
        return getFormattedDate( calendar, "MMM dd yyyy, HH:mm:ss" );
    }

    /**
     * Returns a date string in 'yyyyMMddHHmmss' format for the long time value specified.
     *
     * @param time Milliseconds since Unix Epoch that specifies instance of time.
     * @return Date string in 'yyyyMMddHHmmss' format.
     * @since 1.0
     */
    public String getDate( long time )
    {
        return getDate( defaultDateFormatString, time );
    }

    /**
     * Returns a date string in desired date format for the long time value specified.
     *
     * @param format Date format that this string is to be returned in.
     * @param time   Milliseconds since Unix Epoch that specifies instance of time.
     * @return Date string in desired date format.
     * @since 1.0
     */
    public String getDate( String format, long time )
    {
        String dateString = null;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat( format );
        Date date = new Date( time );
        dateString = simpleDateFormat.format( date );
        return dateString;
    }

    /**
     * Gets a Calendar instance based on the long timestamp value, which represents the number of milliseconds
     * that have elapsed since the Unix Epoch.  Calendars returned using this method will have their milliseconds set
     * to zero (000) automatically
     *
     * @param timestamp Number of millisecond that have elapsed since the Unix Epoch.
     * @return java.util.Calendar instance based on @param timestamp.
     * @since 1.0
     */
    public Calendar getCalendar( long timestamp )
    {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis( timestamp );
        return calendar;
    }

    /**
     * Gets a Calendar instance based on the date string. This string must be in 'yyyyMMddHHmmss' format.
     * Calendars returned using this method will have their milliseconds set to zero (000) automatically.
     *
     * @param dateString Date String used to determine Date.
     * @return java.util.Calendar instance based on @param timestamp.
     * @since 1.0
     */
    public Calendar getCalendar( String dateString )
    {
        return getCalendar( defaultDateFormatString, dateString );
    }

    /**
     * Gets a Calendar instance based on the date string and date format.
     * Calendars returned using this method will have their milliseconds set to zero (000) automatically.
     *
     * @param dateFormat Date Format that the Date String is using.
     * @param dateString Date String used to determine Date.
     * @return java.util.Calendar instance based on @param timestamp.
     * @since 1.0
     */
    public Calendar getCalendar( String dateFormat, String dateString )
    {
        Calendar calendar = null;
        try
        {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat( dateFormat );
            Date date = simpleDateFormat.parse( dateString );
            calendar = getCalendar( date.getTime() );
        }
        catch( ParseException e )
        {
            e.printStackTrace( System.err );
        }
        return calendar;
    }
}
